#include "stdafx.h"
#include "CopyProgressWindow.h"
#include <assert.h>
#include <CommCtrl.h>
#include <math.h>
#include "Resource.h"

static const int kTimeLagInMilliseconds = 500;
static const UINT_PTR kTimerIdForShow = 1;
static const UINT_PTR kTimerIdForHide = 2;

// time lag actions
void CALLBACK ShowOnTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
	::ShowWindow(hwnd, SW_SHOW);
	::KillTimer(hwnd, idEvent);
}
void CALLBACK HideOnTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
	::ShowWindow(hwnd, SW_HIDE);
	::KillTimer(hwnd, idEvent);
}



CopyProgressWindow::CopyProgressWindow()
	: mWindow(0), mInstance(0), mParentWindow(0)
{
}


CopyProgressWindow::~CopyProgressWindow()
{
	if (mWindow)
	{
		::DestroyWindow(mWindow);
		mWindow = 0;
	}
}

// ------------------------------

void CopyProgressWindow::InitWithParameters(HINSTANCE inInstance,
	HWND inParentWindow)
{
	mInstance = inInstance;
	mParentWindow = inParentWindow;
}

void CopyProgressWindow::ShowWithTimeLag(const TCHAR* inDescription)
{
	if (0 == mWindow)
	{
		assert(0 != mInstance && 0 != mParentWindow);
		mWindow = CreateDialog(mInstance, MAKEINTRESOURCE(IDD_DIALOG_COPYPROGRESS),
			mParentWindow, &CopyProgressWindow::DialogProc);
		if (mWindow)
		{
			int x = 20, y = 30, cx = 140, cy = 20;
			if (HWND hLabel = ::GetDlgItem(mWindow, IDC_COPYDESCRIPTION))
			{
				WINDOWINFO wi, wiParent;
				wi.cbSize = wiParent.cbSize = sizeof(WINDOWINFO);
				if (::GetWindowInfo(hLabel, &wi) && 
					::GetWindowInfo(mWindow, &wiParent))
				{
					const RECT& r = wi.rcWindow;
					const RECT& rParent = wiParent.rcClient;
					x = r.left - rParent.left;
					y = r.bottom - rParent.top;
					cx = r.right - r.left;
				}
			}

			::CreateWindowEx(0, PROGRESS_CLASS, nullptr, WS_CHILD | WS_VISIBLE,
				x, y, cx, cy, mWindow, HMENU(IDC_COPYPROGRESSBAR), mInstance,
				nullptr);
		}
	}
	if (mWindow)
	{
		::SetDlgItemText(mWindow, IDC_COPYDESCRIPTION, inDescription);
		mStartTime = ::GetTickCount();
		::SetTimer(mWindow, kTimerIdForShow, kTimeLagInMilliseconds, &ShowOnTimer);
	}
}
void CopyProgressWindow::SetProgress(float inPercent)
{
	if (mWindow && 0.0f <= inPercent && inPercent <= 100.0f)
	{
		::SendDlgItemMessage(mWindow, IDC_COPYPROGRESSBAR, PBM_SETPOS,
			::lroundf(inPercent), 0);
	}
}

void CopyProgressWindow::Hide()
{
	if (mWindow)
	{
		::KillTimer(mWindow, kTimerIdForShow);
		::KillTimer(mWindow, kTimerIdForHide);
		::ShowWindow(mWindow, SW_HIDE);
	}
}

void CopyProgressWindow::HideWithTimeLag()
{
	if (mWindow)
	{
		::KillTimer(mWindow, kTimerIdForShow);
		if (::IsWindowVisible(mWindow))
		{
			DWORD deltaT = ::GetTickCount() - mStartTime;
			const DWORD timeMin = 2 * kTimeLagInMilliseconds;
			if (deltaT < timeMin)
			{
				// do not allow a too quick disappearance,
				// let the window to linger (for user to take notice)
				::SetTimer(mWindow, kTimerIdForHide, timeMin - deltaT, &HideOnTimer);
			}
			else
			{
				::ShowWindow(mWindow, SW_HIDE);
			}
		}
	}
}


bool CopyProgressWindow::IsProcessedDlgMessage(MSG* msg)
{
	return (0 != mWindow && ::IsDialogMessage(mWindow, msg));
}

// --------------------------

// static
INT_PTR CALLBACK CopyProgressWindow::DialogProc(_In_  HWND hwndDlg, _In_  UINT uMsg,
	_In_  WPARAM wParam, _In_  LPARAM lParam)
{
	if (WM_COMMAND == uMsg && IDCANCEL == LOWORD(wParam))
	{
		if (HWND parent = ::GetParent(hwndDlg))
		{
			::PostMessage(parent, kWmMessageCancelCopy, 0, 0);
			return true;
		}
	}
	return false;
}

